<template>
  <div class="timeline-story-gallery" ref="wrapper">
    <div
      class="gallery__large"
      :class="{
        'gallery__large--mask': isCaptionOpen,
      }"
    >
      <transition name="fade">
        <a-image
          :src="gallery?.[currentIndex]?.imgSrc"
          :preview="true"
          fit="contain"
          width="100%"
        />
      </transition>
      <transition name="fade">
        <div
          v-if="gallery?.[currentIndex]?.text"
          class="gallery__large__caption"
          :key="currentIndex"
        >
          <div
            class="caption__collapse collapse"
            :id="`collapse-${timestamp}`"
          >
            {{ gallery[currentIndex].text }}
          </div>
          <div class="caption__display" v-if="!isCaptionOpen">
            {{ gallery[currentIndex].text }}
          </div>
          <button
            class="caption__btn caption__btn--desktop"
            type="button"
            data-bs-toggle="collapse"
            :data-bs-target="`#collapse-${timestamp}`"
            aria-expanded="false"
            :aria-controls="`collapse-${timestamp}`"
            @click="isCaptionOpen = !isCaptionOpen"
          ></button>
          <button
            class="caption__btn d-md-none"
            type="button"
            @click="openCaptionModal(gallery[currentIndex])"
          ></button>
        </div>
      </transition>
    </div>
    <div class="gallery__thumbnail" v-if="gallery && gallery.length > 1">
      <ul class="thumbnail__list" ref="list" @scroll="onListScroll">
        <div
          class="thumbnail__nav__prev"
          v-show="showNavPrev"
          @click="scrollBtnHandller('prev')"
        ></div>
        <li
          class="thumbnail__item"
          v-for="(item, idx) in gallery"
          :key="item.id"
          @click="currentIndex = idx"
        >
          <img :src="item.imgSrc" />
        </li>
        <div
          class="thumbnail__nav__next"
          v-show="showNavNext"
          @click="scrollBtnHandller('next')"
        ></div>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'

// 定义组件名称
defineOptions({
  name: 'TimelineStoryGallery'
})


defineProps<{
  gallery: any[]
}>()

// 定义 emits
const emit = defineEmits<{
  openCaption: [data: { text: string; image: string }]
}>()

// 响应式数据
const currentIndex = ref(0)
const scrollLeft = ref(0)
const scrollWidth = ref(0)
const wrapperWidth = ref(0)
const isCaptionOpen = ref(false)
const timestamp = ref(Date.now())

// 模板引用
const wrapper = ref<HTMLElement | null>(null)
const list = ref<HTMLElement | null>(null)

// 计算属性
const showNavPrev = computed(() => {
  return scrollLeft.value > 0
})

const showNavNext = computed(() => {
  return scrollWidth.value - scrollLeft.value > wrapperWidth.value
})

// 监听器
watch(currentIndex, () => {
  isCaptionOpen.value = false
})

// 方法
const setShowNav = () => {
  const listEl = list.value
  if (listEl) {
    scrollLeft.value = listEl.scrollLeft
    scrollWidth.value = listEl.scrollWidth
  }

  const wrapperEl = wrapper.value
  if (wrapperEl) {
    wrapperWidth.value = wrapperEl.getBoundingClientRect().width
  }
}

const scrollBtnHandller = (dir: string) => {
  const listEl = list.value
  if (!listEl) return

  if (dir === 'next') {
    listEl.scrollLeft += 9999
  } else {
    listEl.scrollLeft -= 9999
  }
}

const onListScroll = () => {
  setShowNav()
}

const openCaptionModal = (obj: any) => {
  emit('openCaption', { text: obj.text || '', image: obj.url })
}

// 生命周期钩子
onMounted(() => {
  nextTick(() => {
    setTimeout(onListScroll, 300)
  })
})
</script>

<style lang="scss" scoped>
.d-md-none {
  display: none!important
}
.timeline-story-gallery {
  width: 100%;

  .gallery__large {
    position: relative;
    width: 100%;
    height: 0;
    padding-bottom: 58.33%;
    overflow: hidden;

    @media (max-width: 767.98px) {
      padding-bottom: 68.75%;
    }

    &.is-crop {
      img {
        object-fit: cover;
      }
    }

    img {
      position: absolute;
      width: 100%;
      height: 100%;
      object-fit: contain;
      cursor: pointer;
    }

    .fade-enter-active,
    .fade-leave-active {
      transition: opacity 0.1s ease-out;
    }

    .fade-enter,
    .fade-leave-to {
      opacity: 0;
    }

    .fade-enter-to,
    .fade-leave {
      opacity: 1;
    }

    &__caption {
      position: absolute;
      left: 0;
      bottom: 0;
      width: 100%;
      padding: 44px 15px 16px 18px;
      background: linear-gradient(180deg, rgba(4, 4, 4, 0) 0%, rgba(0, 0, 0, 0.6) 100%);
      display: flex;
      align-items: flex-end;
      z-index: 1;

      .caption__collapse {
        font-size: 16px;
        line-height: 1.5;
        color: #f8f9fa;

        &.show,
        &.collapsing {
          + .caption__display {
            display: none;
          }
        }
      }

      .caption__display {
        font-size: 14px;
        line-height: 1.4;
        color: #f8f9fa;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
      }

      .caption__btn {
        border: none;
        outline: none;
        background: none;
        width: 24px;
        height: 24px;
        flex-shrink: 0;
        margin-left: 4px;
        background-image: url('');
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        transition: transform 0.3s ease-in-out;
        cursor: pointer;

        &[aria-expanded="true"] {
          transform: rotateZ(180deg);
        }

        &--desktop {
          @media (max-width: 767.98px) {
            display: none;
          }
        }
      }
    }

    &--mask {
      &::after {
        content: '';
        position: absolute;
        height: 100%;
        width: 100%;
        background: linear-gradient(0deg, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6));
      }
    }
  }

  .gallery__thumbnail {
    position: relative;

    .thumbnail__list {
      display: flex;
      margin-top: 12px;
      overflow-x: scroll;
      overflow-y: hidden;
      scroll-behavior: smooth;
      scrollbar-width: none;
      -ms-overflow-style: none;

      &::-webkit-scrollbar {
        display: none;
      }

      @media (max-width: 767.98px) {
        margin-top: 8px;
      }

      .thumbnail__item {
        flex-shrink: 0;
        width: 87.4px;
        height: 55px;
        cursor: pointer;

        @media (max-width: 900px) {
          width: 80px;
        }

        @media (max-width: 767.98px) {
          width: 75px;
        }

        &:not(:last-of-type) {
          margin-right: 10.6px;

          @media (max-width: 900px) {
            margin-right: 6px;
          }

          @media (max-width: 767.98px) {
            margin-right: 8px;
          }
        }

        img {
          width: 100%;
          height: 100%;
          object-fit: contain;
        }
      }

      .thumbnail__nav {
        &__prev,
        &__next {
          position: absolute;
          width: 33px;
          height: 100%;
          background-color: #f8f9fa;
          display: flex;
          align-items: center;
          justify-content: center;
          z-index: 1;
          cursor: pointer;

          @media (max-width: 1023.98px) {
            width: 28px;
          }

          @media (max-width: 767.98px) {
            box-shadow: 0 4px 4px rgba(255, 255, 255, 0.2);
          }

          &::after {
            content: '';
            width: 24px;
            height: 24px;
            background-image: url('');
            background-size: contain;
            background-repeat: no-repeat;
            background-position: center;

            @media (max-width: 1023.98px) {
              width: 14px;
              height: 14px;
            }
          }
        }

        &__prev {
          left: -1px;

          &::after {
            transform: scale(-1);
          }
        }

        &__next {
          right: -1px;
        }
      }
    }
  }
}
</style>